package com.alibaba.citrus.cr.sales.plan.facade.service;

import com.alibaba.citrus.cr.common.exception.FacadeException;
import com.alibaba.citrus.cr.common.util.DateUtils;
import com.alibaba.citrus.cr.sales.plan.dto.DimensionalityIdentityInterface;
import com.alibaba.citrus.cr.sales.plan.dto.api.request.DimensionDTO;
import com.alibaba.citrus.cr.sales.plan.dto.api.request.MonthContractAndRollingCountResponse;
import com.alibaba.citrus.cr.sales.plan.dto.api.request.QueryContractByCustomerDimensionRequest;
import com.alibaba.citrus.cr.sales.plan.dto.api.request.QuerySalesPlanRequest;
import com.alibaba.citrus.cr.sales.plan.model.enums.ContractStatDimensionEnum;
import com.alibaba.citrus.cr.sales.plan.model.enums.SalesPlanModelEnum;
import com.alibaba.citrus.cr.sales.plan.model.enums.SalesStatBizTypeEnum;
import com.alibaba.citrus.cr.sales.plan.model.enums.StatPoolTypeEnum;
import com.alibaba.citrus.cr.sales.plan.repository.ContractRepository;
import com.alibaba.citrus.cr.sales.plan.repository.SalesPlanRepository;
import com.alibaba.citrus.cr.sales.plan.repository.SalesPlanScItemExtendRepository;
import com.alibaba.citrus.cr.sales.plan.repository.request.PageQueryPlanScItemExtendRepoRequest;
import com.alibaba.citrus.cr.sales.plan.sdo.SalesPlanLineSDO;
import com.alibaba.citrus.cr.sales.plan.sdo.SalesPlanSDO;
import com.alibaba.citrus.cr.sales.plan.sdo.SalesPlanScItemExtendSDO;
import com.alibaba.cz.base.tool.StringUtil;
import com.alibaba.cz.base.tool.log.Log;
import com.alibaba.cz.base.tool.message.ErrorMessage;
import com.alibaba.cz.base.tool.page.PageResult;
import com.alibaba.fastjson.JSON;
import com.alibaba.lattice2.epoch.sdk.model.Result;
import com.google.common.collect.Lists;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author luyi
 * @date 2021/10/20 7:34 下午
 */
@Component
public class SalesPlanCommonService {
    private static final Log log = Log.getLogger(SalesPlanCommonService.class);

    @Resource
    private SalesPlanRepository salesPlanRepository;

    @Resource
    private SalesPlanScItemExtendRepository salesPlanScItemExtendRepository;

    @Resource
    private ContractRepository contractRepository;

    private static final Integer DEFAULT_PAGE_SIZE = 1000;

    private static final Integer ZERO = 0;

    /**
     * 校验计划ID
     * @param planId
     * @return
     */
    public SalesPlanSDO checkSalesPlan(String planId){
        QuerySalesPlanRequest querySalesPlanRequest = new QuerySalesPlanRequest();
        querySalesPlanRequest.setId(planId);
        SalesPlanSDO salesPlan = salesPlanRepository.load(querySalesPlanRequest);
        if (Objects.isNull(salesPlan)){
            throw new FacadeException(ErrorMessage.code("OTS-02-002-00-16-001"));
        }
        return salesPlan;
    }

    /**
     * 校验维度身份
     * @param identityInterface
     * @return
     */
    public DimensionDTO checkBizType(SalesPlanSDO salesPlan, DimensionalityIdentityInterface identityInterface){
        if (identityInterface.getBizType() == null || StringUtil.isBlank(identityInterface.getBizId())){
            throw new FacadeException(ErrorMessage.code("OTS-02-002-02-15-007"));
        }
        DimensionDTO result = new DimensionDTO();
        if (identityInterface.getBizType() < SalesStatBizTypeEnum.BUSINESS_UNIT.getOrganizationType()){
            if (salesPlan != null) {
                result.setBizType(SalesStatBizTypeEnum.BUSINESS_UNIT.getBizType());
                result.setBizId(salesPlan.getOrgBusinessUnitCode());
            }
            return result;
        }
        SalesStatBizTypeEnum byOrganizationType = SalesStatBizTypeEnum.getByOrganizationType(identityInterface.getBizType());
        if (byOrganizationType == null){
            throw new FacadeException(ErrorMessage.code("OTS-02-002-02-15-007"));
        }
        result.setBizType(byOrganizationType.getBizType());
        result.setBizId(identityInterface.getBizId());
        return result;
    }

    /**
     * 检查Result
     * @param result
     * @param errorCode
     * @return
     */
    public static Boolean resultCheck(Result<?> result, String errorCode) {
        if (result == null || !result.isSuccess() || result.getResult() == null) {
            if (Objects.isNull(errorCode)){
                return false;
            }
            throw new FacadeException(errorCode);
        }
        if (result.getResult() instanceof List && ((List<?>) result.getResult()).isEmpty()) {
            if (Objects.isNull(errorCode)){
                return false;
            }
            throw new FacadeException(errorCode);
        }
        return true;
    }

    /**
     * 参数拼接 param1-param2-param3
     * @param param
     * @return
     */
    public static String getCombinationKey(String... param){
        StringBuilder result = new StringBuilder();
        boolean first = true;
        for (String a: param) {
            if (StringUtil.isBlank(a)){
                continue;
            }
            if (first){
                result = new StringBuilder(a);
                first = false;
            }else {
                result.append("-").append(a);
            }
        }
        return result.toString();
    }

    public static <T> void checkBlank(Set<T> collect, T t){
        if (t instanceof String){
            if (StringUtils.isNotBlank((String)t)){
                collect.add(t);
            }
        }
    }

    public List<SalesPlanScItemExtendSDO> fetchPlanScItemExtendForDepartment(String planId, List<Integer> statusList) {
        int page = 1;
        List<SalesPlanScItemExtendSDO> salesPlanScItemExtendSDOS = Lists.newArrayList();
        PageResult<List<SalesPlanScItemExtendSDO>> pageResult = fetchPlanScItemExtendListForDepartment(planId, statusList, page);
        while (null != pageResult) {
            List<SalesPlanScItemExtendSDO> salesPlanScItemExtendSDOList = pageResult.getContent();
            salesPlanScItemExtendSDOS.addAll(salesPlanScItemExtendSDOList);
            // 已经是最后一页
            if (pageResult.getContent().size() < DEFAULT_PAGE_SIZE) {
                break;
            }
            pageResult = fetchPlanScItemExtendListForDepartment(planId, statusList, ++page);
        }
        if (CollectionUtils.isEmpty(salesPlanScItemExtendSDOS)) {
            throw new FacadeException(ErrorMessage.code("OTS-02-004-01-16-016"));
        }
        return salesPlanScItemExtendSDOS;
    }

    private PageResult<List<SalesPlanScItemExtendSDO>> fetchPlanScItemExtendListForDepartment(String planId, List<Integer> statusList, Integer page) {
        // 批量查询部门的计划货品数量
        PageQueryPlanScItemExtendRepoRequest pageQuery = new PageQueryPlanScItemExtendRepoRequest();
        // planId就能标识一个公司
        pageQuery.setPlanId(planId);
        pageQuery.setBizType(SalesStatBizTypeEnum.SALES_DEPARTMENT.getBizType());
        pageQuery.setPoolType(StatPoolTypeEnum.SC_ITEM.getPoolType());
        pageQuery.setModel(SalesPlanModelEnum.PLAN_MODEL.getModel());
        // 待发布的  已发布的
        //pageQuery.setStatus(status);
        pageQuery.setStatusList(statusList);
        pageQuery.setPage(page);
        pageQuery.setLimit(DEFAULT_PAGE_SIZE);
        log.info("查询月度计划所有部门的任务量汇总数据参数{}", JSON.toJSONString(pageQuery));
        PageResult<List<SalesPlanScItemExtendSDO>> pageResult = salesPlanScItemExtendRepository.pageQueryPlanScItemExtendList(pageQuery);
        log.info("查询月度计划所有部门的任务量汇总数据结果{}", JSON.toJSONString(pageResult));
        if (null == pageResult || CollectionUtils.isEmpty(pageResult.getContent())) {
            return null;
        }
        return pageResult;
    }

    /**
     * 获取并设置合同量数据
     *
     * @param salesPlanLineSDOs
     * @return
     */
    public List<SalesPlanLineSDO> fillContractInfoAndModifySalesPlanDetails(List<SalesPlanLineSDO> salesPlanLineSDOs) {
        if (CollectionUtils.isEmpty(salesPlanLineSDOs)) {
            return Lists.newArrayList();
        }
        //1、构造查询参数
        QueryContractByCustomerDimensionRequest queryContractByCustomerDimensionRequest = buildQueryContractCountAndMoneyRequest(salesPlanLineSDOs);
        List<MonthContractAndRollingCountResponse> contResponses = contractRepository.queryQuantityListByAddressAndScItem(queryContractByCustomerDimensionRequest);
//        if (contResponses.size() < 1) {
//            return Lists.newArrayList();
//        }
        return salesPlanLineSDOs.stream().peek(salesPlanLineSDO -> {
            if (contResponses.size() < 1) {
                setZero(salesPlanLineSDO);
            } else {
                List<MonthContractAndRollingCountResponse> countResponses = contResponses.stream().filter(res ->
                        res.getCustomerCode().equals(salesPlanLineSDO.getCustomerCode())
                                && res.getCustomerAddress().equals(salesPlanLineSDO.getCustomerAddress())
                                && res.getCustomerAddressId().equals(salesPlanLineSDO.getCustomerAddressId())
                                && res.getScItemId().equals(salesPlanLineSDO.getScItemId())).collect(Collectors.toList());
                if (CollectionUtils.isNotEmpty(countResponses)) {
                    MonthContractAndRollingCountResponse response = countResponses.stream().findFirst().get();
                    salesPlanLineSDO.setMonthContractCount(response.getMonthContractCount());
                    salesPlanLineSDO.setMonthContractMoney(response.getMonthContractMoney());
                    if (null == salesPlanLineSDO.getM1RollingPlanCount()) {
                        salesPlanLineSDO.setM1RollingPlanCount(response.getM1RollingPlanCount());
                    }
                    if (null == salesPlanLineSDO.getM2RollingPlanCount()) {
                        salesPlanLineSDO.setM2RollingPlanCount(response.getM2RollingPlanCount());
                    }
                    if (null == salesPlanLineSDO.getM3RollingPlanCount()) {
                        salesPlanLineSDO.setM3RollingPlanCount(response.getM3RollingPlanCount());
                    }
                    salesPlanLineSDO.setBeforeMonthContractMoney(response.getBeforeMonthContractMoney());
                } else {
                    setZero(salesPlanLineSDO);
                }
            }
        }).collect(Collectors.toList());
    }

    private void setZero(SalesPlanLineSDO salesPlanLineSDO) {
        salesPlanLineSDO.setMonthContractCount(ZERO);
        salesPlanLineSDO.setMonthContractMoney(ZERO.longValue());
        if (null == salesPlanLineSDO.getM1RollingPlanCount()) {
            salesPlanLineSDO.setM1RollingPlanCount(ZERO);
        }
        if (null == salesPlanLineSDO.getM2RollingPlanCount()) {
            salesPlanLineSDO.setM2RollingPlanCount(ZERO);
        }
        if (null == salesPlanLineSDO.getM3RollingPlanCount()) {
            salesPlanLineSDO.setM3RollingPlanCount(ZERO);
        }
        salesPlanLineSDO.setBeforeMonthContractMoney(ZERO.longValue());
    }

    private QueryContractByCustomerDimensionRequest buildQueryContractCountAndMoneyRequest(List<SalesPlanLineSDO> salesPlanLineSDOs) {
        QueryContractByCustomerDimensionRequest queryContractByCustomerDimensionRequest = new QueryContractByCustomerDimensionRequest();
        SalesPlanLineSDO sdo = salesPlanLineSDOs.stream().findFirst().get();
        QuerySalesPlanRequest querySalesPlanRequest = new QuerySalesPlanRequest();
        querySalesPlanRequest.setId(sdo.getPlanId());
        SalesPlanSDO salesPlanSDO = salesPlanRepository.load(querySalesPlanRequest);
        if (null == salesPlanSDO) {
            return null;
        }
        String planTime = salesPlanSDO.getPlanTime();
        String time = DateUtils.stampToDate(planTime);
        List<String> stringList = getFromPlanTime(time);
        String contractYear = null;
        String planMonth = null;
        if (stringList.size() == 2) {
            //年 月
            contractYear = stringList.get(0);
            planMonth = stringList.get(1);
        }
        List<String> customerCodes = salesPlanLineSDOs.stream().map(SalesPlanLineSDO::getCustomerCode).distinct().filter(StringUtils::isNotEmpty).collect(Collectors.toList());
        List<String> customerAddress = salesPlanLineSDOs.stream().map(SalesPlanLineSDO::getCustomerAddress).distinct().filter(StringUtils::isNotEmpty).collect(Collectors.toList());
        List<String> customerAddressIds = salesPlanLineSDOs.stream().map(SalesPlanLineSDO::getCustomerAddressId).distinct().filter(StringUtils::isNotEmpty).collect(Collectors.toList());
        List<String> scItemIds = salesPlanLineSDOs.stream().map(SalesPlanLineSDO::getScItemId).distinct().filter(StringUtils::isNotEmpty).collect(Collectors.toList());
        queryContractByCustomerDimensionRequest.setContractYear(contractYear);
        queryContractByCustomerDimensionRequest.setPlanMonth(planMonth);
        queryContractByCustomerDimensionRequest.setCustomerCodes(customerCodes);
        queryContractByCustomerDimensionRequest.setCustomerAddresses(customerAddress);
        if (CollectionUtils.isNotEmpty(customerAddressIds)) {
            queryContractByCustomerDimensionRequest.setCustomerAddressesIds(customerAddressIds);
        }

        queryContractByCustomerDimensionRequest.setScItemIds(scItemIds);
        queryContractByCustomerDimensionRequest.setType(ContractStatDimensionEnum.CUSTOMER_SC_ITEM.getCode());
        return queryContractByCustomerDimensionRequest;
    }

    /**
     * 从计划时间中获取计划年月
     *
     * @param time
     * @return
     * @throws Exception
     */
    private static List<String> getFromPlanTime(String time) {
        List<String> timeList = new ArrayList<>();
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//注意月份是MM
        Calendar calendar = Calendar.getInstance();
        try {
            calendar.setTime(simpleDateFormat.parse(time));
        } catch (ParseException e) {
            e.printStackTrace();
        }
        int month = calendar.get(Calendar.MONTH) + 1;//获取月份
        int year = calendar.get(Calendar.YEAR);//获取年份
        timeList.add(Integer.toString(year));
        timeList.add(Integer.toString(month));
        return timeList;
    }
}
